package com.example.hkrfidplugin_testmodule;

import android.content.Context;
import android.util.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.hikvision.HikUhfSdkManager;
import com.hikvision.bean.GenData;
import com.hikvision.bean.UHFTAGInfo;
import com.hikvision.callback.ServiceConnectCallback;
import com.hikvision.constant.UHFBank;
import com.hikvision.uhfservice.IAdilCallback;

import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;

import android.content.ComponentName;
import android.os.IBinder;
import android.os.RemoteException;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 海康威视RFID插件
 * 基于海康UHF SDK封装，提供uniapp调用接口
 */
public class hkrfidModule extends UniModule {

    private static final String TAG = "HikvisionRFID";

    private HikUhfSdkManager uhfSdk;
    private volatile boolean isConnected = false;  // 添加volatile保证线程安全
    private ExecutorService executorService;
    private IAdilCallback inventoryCallback;  // 循环盘点回调
    private volatile boolean isInventoryRunning = false;  // 循环盘点状态
    private List<Map<String, Object>> inventoryResults;  // 盘点结果列表
    private UniJSCallback inventoryCallbackJS;  // JS回调

    private Context mContext;

    @Override
    public void onActivityCreate() {
        Log.d(TAG, "457848");
        super.onActivityCreate();
        // 只创建线程，不急着拿 SDK
        executorService = Executors.newSingleThreadExecutor();
        uhfSdk = HikUhfSdkManager.getInstance(mWXSDKInstance.getContext());
        Log.d(TAG, "uhfSdk");
        inventoryResults = new CopyOnWriteArrayList<>();
        initInventoryCallback();
        Log.d(TAG, "HikvisionRFIDModule initialized");
    }

    /**
     * 第一次 JS 调用时再实例化 SDK，保证上下文已就绪
     */
    private void ensureSDK() {
        mContext = (Context)this;

        Log.d(TAG, "3333");
        if (uhfSdk == null) {
            Log.d(TAG, "ensureSDK uhfsdk为null");
            Context ctx = mWXSDKInstance != null ? mWXSDKInstance.getContext() : null;
            Log.d(TAG, "ensureSDK ctx:"+ctx);
            if (ctx == null) {
                Log.e(TAG, "WXSDKInstance or context is null!");
                return;
            }
            Log.d(TAG, "ensureSDK uhfSdk 000");
            if (uhfSdk == null){
                Log.d(TAG, "ensureSDK 11, uhfSdk is null ");
            }else{
                Log.d(TAG, "ensureSDK 11, uhfSdk is not null ");
            }
            uhfSdk = HikUhfSdkManager.getInstance(ctx);
            if (uhfSdk == null){
                Log.d(TAG, "ensureSDK 22, uhfSdk is null ");
            }else{
                Log.d(TAG, "ensureSDK 22, uhfSdk is not null ");
            }
        }
    }

    /**
     * 初始化UHF服务
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void initUHF(UniJSCallback callback) {
        Log.d(TAG, "Initializing UHF service");
        ensureSDK();          // 关键：延后初始化
        if (uhfSdk == null) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -1);
                result.put("message", "UHF SDK未初始化");
                callback.invoke(result);
            }
            return;
        }
        Log.d(TAG, "initUHF, executorService: "+executorService.toString());
        executorService.execute(() -> {
            try {
                uhfSdk.init(new ServiceConnectCallback() {
                    @Override
                    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                        Log.d(TAG, "UHF service connected");
                        isConnected = true;

                        if (callback != null) {
                            Map<String, Object> result = new HashMap<>();
                            result.put("code", 0);
                            result.put("message", "UHF服务连接成功");
                            result.put("connected", true);
                            callback.invoke(result);
                        }
                    }

                    @Override
                    public void onServiceDisconnected(ComponentName componentName) {
                        Log.d(TAG, "UHF service disconnected");
                        isConnected = false;

                        if (callback != null) {
                            Map<String, Object> result = new HashMap<>();
                            result.put("code", -2);
                            result.put("message", "UHF服务连接断开");
                            result.put("connected", false);
                            callback.invoke(result);
                        }
                    }
                });
            } catch (Exception e) {
                Log.e(TAG, "Error initializing UHF service", e);
                if (callback != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", -3);
                    result.put("message", "初始化UHF服务失败: " + e.getMessage());
                    callback.invoke(result);
                }
            }
        });
    }

    /**
     * 单步盘点（读取单个RFID标签）
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void inventorySingleTag(UniJSCallback callback) {
        Log.d(TAG, "Performing single tag inventory");

        if (!isConnected) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -1);
                result.put("message", "UHF服务未连接");
                callback.invoke(result);
            }
            return;
        }

        executorService.execute(() -> {
            try {
                UHFTAGInfo tagInfo = uhfSdk.inventorySingleTag();

                if (tagInfo != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", 0);
                    result.put("message", "盘点成功");
                    result.put("tagInfo", convertTagInfoToMap(tagInfo));
                    callback.invoke(result);
                } else {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", 1);
                    result.put("message", "未检测到标签");
                    callback.invoke(result);
                }
            } catch (Exception e) {
                Log.e(TAG, "Error during inventory", e);
                if (callback != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", -2);
                    result.put("message", "盘点失败: " + e.getMessage());
                    callback.invoke(result);
                }
            }
        });
    }

    /**
     * 读取标签数据
     * @param params 读取参数
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void readData(JSONObject params, UniJSCallback callback) {
        Log.d(TAG, "Reading tag data");

        if (!isConnected) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -1);
                result.put("message", "UHF服务未连接");
                callback.invoke(result);
            }
            return;
        }

        try {
            String password = params.getString("password");
            int bank = params.getIntValue("bank");
            int address = params.getIntValue("address");
            int length = params.getIntValue("length");

            executorService.execute(() -> {
                try {
                    GenData genData = new GenData(password, bank, address, length);
                    String data = uhfSdk.readData(genData);

                    Map<String, Object> result = new HashMap<>();
                    result.put("code", 0);
                    result.put("message", "读取数据成功");
                    result.put("data", data);
                    callback.invoke(result);

                } catch (Exception e) {
                    Log.e(TAG, "Error reading data", e);
                    if (callback != null) {
                        Map<String, Object> result = new HashMap<>();
                        result.put("code", -2);
                        result.put("message", "读取数据失败: " + e.getMessage());
                        callback.invoke(result);
                    }
                }
            });

        } catch (Exception e) {
            Log.e(TAG, "Invalid parameters for readData", e);
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -3);
                result.put("message", "参数错误: " + e.getMessage());
                callback.invoke(result);
            }
        }
    }

    /**
     * 释放UHF服务
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void releaseUHF(UniJSCallback callback) {
        Log.d(TAG, "Releasing UHF service");

        executorService.execute(() -> {
            try {
                boolean result = uhfSdk.free();
                isConnected = false;

                if (callback != null) {
                    Map<String, Object> response = new HashMap<>();
                    response.put("code", 0);
                    response.put("message", "UHF服务已释放");
                    response.put("success", result);
                    callback.invoke(response);
                }
            } catch (Exception e) {
                Log.e(TAG, "Error releasing UHF service", e);
                if (callback != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", -1);
                    result.put("message", "释放UHF服务失败: " + e.getMessage());
                    callback.invoke(result);
                }
            }
        });
    }

    /**
     * 获取连接状态
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void getConnectionStatus(UniJSCallback callback) {
        if (callback != null) {
            Map<String, Object> result = new HashMap<>();
            result.put("connected", isConnected);
            callback.invoke(result);
        }
    }

    /**
     * 开始循环盘点
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void startInventoryLoop(UniJSCallback callback) {
        Log.d(TAG, "Starting inventory loop");
        Log.d(TAG, "startInventoryLoop, isConnected: "+isConnected);
        if (uhfSdk == null){
            Log.d(TAG, "startInventoryLoop, uhfSdk is null ");
        }else{
            Log.d(TAG, "startInventoryLoop, uhfSdk is not null ");
        }
        Log.d(TAG, "startInventoryLoop, executorService: "+executorService.toString());

        if (!isConnected) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -1);
                result.put("message", "UHF服务未连接");
                callback.invoke(result);
            }
            return;
        }

        if (isInventoryRunning) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -2);
                result.put("message", "循环盘点已在运行中");
                callback.invoke(result);
            }
            return;
        }

        executorService.execute(() -> {
            try {
                // 注册回调
                boolean registerResult = uhfSdk.registerCallback(inventoryCallback);
                if (!registerResult) {
                    if (callback != null) {
                        Map<String, Object> result = new HashMap<>();
                        result.put("code", -3);
                        result.put("message", "注册回调失败");
                        callback.invoke(result);
                    }
                    return;
                }

                // 开始循环盘点
                int result = uhfSdk.startInventoryTag();
                if (result == 0) {
                    isInventoryRunning = true;
                    inventoryCallbackJS = callback;
                    inventoryResults.clear();

                    if (callback != null) {
                        Map<String, Object> response = new HashMap<>();
                        response.put("code", 0);
                        response.put("message", "循环盘点已开始");
                        response.put("status", "started");
                        callback.invoke(response);
                    }
                } else {
                    // 失败时注销回调
                    uhfSdk.unregisterCallback();

                    if (callback != null) {
                        Map<String, Object> response = new HashMap<>();
                        response.put("code", -4);
                        response.put("message", "开始循环盘点失败，错误码: " + result);
                        callback.invoke(response);
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "Error starting inventory loop", e);
                if (callback != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", -5);
                    result.put("message", "开始循环盘点异常: " + e.getMessage());
                    callback.invoke(result);
                }
            }
        });
    }

    /**
     * 停止循环盘点
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void stopInventoryLoop(UniJSCallback callback) {
        Log.d(TAG, "Stopping inventory loop");

        if (!isConnected) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -1);
                result.put("message", "UHF服务未连接");
                callback.invoke(result);
            }
            return;
        }

        if (!isInventoryRunning) {
            if (callback != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", -2);
                result.put("message", "循环盘点未运行");
                callback.invoke(result);
            }
            return;
        }

        executorService.execute(() -> {
            try {
                // 停止循环盘点
                int result = uhfSdk.stopInventory();

                // 注销回调
                uhfSdk.unregisterCallback();

                isInventoryRunning = false;

                if (callback != null) {
                    Map<String, Object> response = new HashMap<>();
                    response.put("code", 0);
                    response.put("message", "循环盘点已停止");
                    response.put("status", "stopped");
                    response.put("results", new ArrayList<>(inventoryResults));
                    callback.invoke(response);
                }

                // 清理回调引用
                inventoryCallbackJS = null;

            } catch (Exception e) {
                Log.e(TAG, "Error stopping inventory loop", e);
                if (callback != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", -3);
                    result.put("message", "停止循环盘点异常: " + e.getMessage());
                    callback.invoke(result);
                }
            }
        });
    }

    /**
     * 检查循环盘点状态
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void getInventoryLoopStatus(UniJSCallback callback) {
        if (callback != null) {
            Map<String, Object> result = new HashMap<>();
            result.put("running", isInventoryRunning);
            result.put("connected", isConnected);
            result.put("resultCount", inventoryResults.size());
            callback.invoke(result);
        }
    }

    /**
     * 获取循环盘点结果
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void getInventoryResults(UniJSCallback callback) {
        if (callback != null) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("results", new ArrayList<>(inventoryResults));
            result.put("count", inventoryResults.size());
            callback.invoke(result);
        }
    }

    /**
     * 清除循环盘点结果
     * @param callback 回调函数
     */
    @UniJSMethod(uiThread = false)
    public void clearInventoryResults(UniJSCallback callback) {
        inventoryResults.clear();
        if (callback != null) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "循环盘点结果已清除");
            callback.invoke(result);
        }
    }

    /**
     * 初始化循环盘点回调
     */
    private void initInventoryCallback() {
        inventoryCallback = new IAdilCallback.Stub() {
            @Override
            public void message(int i) throws RemoteException {
                Log.d(TAG, "Inventory callback message: " + i);
                // 升级进度回调，这里不需要处理
            }

            @Override
            public void onCommandStatus(int status) throws RemoteException {
                Log.d(TAG, "Inventory callback onCommandStatus: " + status);
                // 接口调用失败状态码回调
                if (status != 0 && inventoryCallbackJS != null) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", -6);
                    result.put("message", "循环盘点错误，状态码: " + status);
                    result.put("status", "error");
                    result.put("errorCode", status);
                    inventoryCallbackJS.invoke(result);
                }
            }
        };
    }

    /**
     * 处理接收到的标签数据
     * 注意：海康SDK的循环盘点通过回调机制返回标签数据
     * 这里假设SDK会通过某种方式调用此方法来传递标签数据
     */
    private void handleTagData(UHFTAGInfo tagInfo) {
        if (tagInfo != null && isInventoryRunning) {
            Map<String, Object> tagData = convertTagInfoToMap(tagInfo);
            inventoryResults.add(tagData);

            // 实时回调给JS
            if (inventoryCallbackJS != null) {
                Map<String, Object> result = new HashMap<>();
                result.put("code", 0);
                result.put("message", "检测到标签");
                result.put("status", "tagDetected");
                result.put("tagInfo", tagData);
                result.put("totalCount", inventoryResults.size());
                inventoryCallbackJS.invoke(result);
            }

            Log.d(TAG, "Tag detected: " + tagInfo.getEPC());
        }
    }

    /**
     * 将UHFTAGInfo转换为Map对象
     */
    private Map<String, Object> convertTagInfoToMap(UHFTAGInfo tagInfo) {
        Map<String, Object> map = new HashMap<>();
        if (tagInfo != null) {
            map.put("epc", tagInfo.getEPC());
            map.put("tid", tagInfo.getTid());
            map.put("user", tagInfo.getUser());
            map.put("rssi", tagInfo.getRssi());
            map.put("ant", tagInfo.getAnt());
//            map.put("freq", tagInfo.getFreq());
//            map.put("readCount", tagInfo.getReadCount());
//            map.put("protocol", tagInfo.getProtocol());
//            map.put("timestamp", tagInfo.getTimestamp());
        }
        return map;
    }

    @Override
    public void onActivityDestroy() {
        // 先执行清理逻辑
        if (isInventoryRunning) {
            try {
                uhfSdk.stopInventory();
                uhfSdk.unregisterCallback();
                isInventoryRunning = false;
            } catch (Exception e) {
                Log.e(TAG, "Error stopping inventory loop", e);
            }
        }

        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
        }
        if (uhfSdk != null && isConnected) {
            try {
                uhfSdk.free();
                isConnected = false;
            } catch (Exception e) {
                Log.e(TAG, "Error freeing UHF SDK", e);
            }
        }
        // 最后调用父类方法
        super.onActivityDestroy();
    }

    // 添加生命周期钩子方法
    public void onAppCreate() {
        Log.d(TAG, "App create callback");
    }

    public void onAppDestroy() {
        Log.d(TAG, "App destroy callback");
        onActivityDestroy(); // 复用清理逻辑
    }
}